package com.ruoyi.rsikManage.task;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.HKISAPI.service.ISAPIService;
import com.ruoyi.common.GenericMethodsService;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.rsikManage.domain.AlarmEvent;
import com.ruoyi.rsikManage.domain.BroadCast;
import com.ruoyi.rsikManage.domain.MonitorPoint;
import com.ruoyi.rsikManage.domain.TUnitConfig;
import com.ruoyi.rsikManage.domain.common.RiskObject;
import com.ruoyi.rsikManage.domain.vo.BroadCastRequestVo;
import com.ruoyi.rsikManage.service.*;
import lombok.Getter;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletContext;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Component
@Getter
@Setter
public class MonitorPointScheduler implements SchedulingConfigurer {

    @Value("${scheduler.monitorStatusUpdateCron}")
    private String initialMonitorStatusUpdateCron;
    private boolean isLastReceiveCornErr;
    @Value("${scheduler.monitorStatusUpdateCron}")
    private String monitorStatusUpdateCron;
    @Value("${hk.switch}")
    private String HK_SWITCH;
    @Value("${system.name}")
    private String SYSTEM_NAME;
    @Value("${system.permissionVersion}")
    private String SYSTEM_PermissionVersion;
    @Value("${jy.channel_name_is_filter}")
    private String CHANNEL_NAME_IS_FILTER;

    @Autowired
    JyService jyService;
    @Autowired
    MonitorPointService monitorPointService;
    @Autowired
    MonitorPointHistoryService monitorPointHistoryService;
    @Autowired
    BroadcastService broadcastService;
    @Autowired
    CustomConfigurationService customConfigurationService;
    @Autowired
    ServletContext servletContext;

    @Autowired
    ISAPIService iSAPIService;
    @Autowired
    ITUnitConfigService tUnitConfigService;

    @Autowired
    TokenService tokenService;

    @Autowired
    private GenericMethodsService genericMethodsService;
    private Object JYMap;

    // 获取 Logger 实例
    private static final Logger logger = LoggerFactory.getLogger(MonitorPointScheduler.class);

//    @Override
//    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
//        taskRegistrar.addTriggerTask(() -> {
//            updateMonitorStatusTask2();
//        }, triggerContext -> {
//            // 使用CronTrigger触发器，动态修改cron表达式来操作循环规则
//            CronTrigger cronTrigger;
//            if (isLastReceiveCornErr) {
//                cronTrigger = new CronTrigger(initialMonitorStatusUpdateCron);
//            }else {
//                try {
//                    cronTrigger = new CronTrigger(monitorStatusUpdateCron);
//                }catch (IllegalArgumentException e) {
//                    System.out.println("上次接收的monitorStatusUpdateCron:\""+ monitorStatusUpdateCron + "\" 格式错误，monitorStatusUpdateCron 更新为初始值======");
//                    cronTrigger = new CronTrigger(initialMonitorStatusUpdateCron);
//                    isLastReceiveCornErr = true;
//                }
//            }
//            return cronTrigger.nextExecutionTime(triggerContext);
//        });
//    }
    /**
     * @author wxx
     * @description
     * @date 2024/10/23
     * 新增注释说明 改用updateMonitorStatusTask2V2();
     *
     */
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        // 添加一个触发任务到任务注册表中
        taskRegistrar.addTriggerTask(
                () -> {
                    // 定义要执行的任务: 调用更新监控状态的方法
                    updateMonitorStatusTask2V2();
                },
                triggerContext -> {
                    // 创建一个 CronTrigger 触发器，根据条件选择不同的 Cron 表达式
                    CronTrigger cronTrigger;
                    if (isLastReceiveCornErr) {
                        // 如果上一次接收到的 Cron 表达式有误，使用初始的 Cron 表达式
                        cronTrigger = new CronTrigger(initialMonitorStatusUpdateCron);
                    } else {
                        try {
                            // 尝试使用新的 Cron 表达式创建 CronTrigger
                            cronTrigger = new CronTrigger(monitorStatusUpdateCron);
                        } catch (IllegalArgumentException e) {
                            // 如果新的 Cron 表达式格式错误，打印错误信息并恢复为初始的 Cron 表达式
                            System.out.println("上次接收的monitorStatusUpdateCron:\"" + monitorStatusUpdateCron + "\" 格式错误，monitorStatusUpdateCron 更新为初始值======");
                            cronTrigger = new CronTrigger(initialMonitorStatusUpdateCron);
                            isLastReceiveCornErr = true; // 设置标志位表示最近一次的 Cron 表达式有误
                        }
                    }
                    // 返回下次执行的时间，基于当前的 CronTrigger
                    return cronTrigger.nextExecutionTime(triggerContext);
                }
        );
    }
    @Transactional
    public void updateMonitorStatusTask2(){
        List<MonitorPoint> allList=new ArrayList<>();
        List<MonitorPoint> list=new ArrayList<>();
        System.out.println("--------------更新监控点：" + LocalTime.now());
//        String monitorListJsonStr = jyService.getChannelListWithDevice();
        if("true".equals(HK_SWITCH)){
            allList = (List<MonitorPoint>)iSAPIService.getChannels().get("monitorPoints");
        }else {
            allList = toMonitorList(jyService.getChannelListWithDevice());
        }

        for (MonitorPoint monitorPoint : allList) {
            String name = monitorPoint.getName();
            if (name.contains("_通道_")) {
//                System.out.println("找到了含有 '_通道_' 的监控点名称: " + name);
            }else {
                list.add(monitorPoint);
            }
        }
        //如果是电子围栏 则对应的监控点数据更新至监测设备
        if ("ef".equals(SYSTEM_NAME) && list != null && !list.isEmpty()){

        }

        monitorPointService.mergeMonitorListToMonitorTable(list);
        monitorPointService.deleteMonitorNotInList(list);
        //获取离线时间超过设定时间并且还有没发送过报警信息的所有监控点
        List<MonitorPoint> monitorListThatOfflineTimeout = monitorPointService.selectMonitorsThatNeedToSendOfflineAlarm();
        if (monitorListThatOfflineTimeout != null && monitorListThatOfflineTimeout.size() > 0) {
            //报警表中新增这些监控点的离线超时报警
            monitorPointService.insertMonitorOfflineAlarm(monitorListThatOfflineTimeout);
            //更新这些监控点的isOfflineAlarmBeenSent(离线超时报警发送状态)为已经发送
            monitorPointService.updateAlarmStatusAsSent(monitorListThatOfflineTimeout);
            //广播播报
            if(servletContext.getAttribute("broadcastPlaySwitch").equals(1)) {
                for (MonitorPoint monitor : monitorListThatOfflineTimeout) {
                    List<BroadCast> broadcasts = broadcastService.selectMonitorAssociatedBroadcasts(monitor.getApeId());
                    Integer[] broadcastIds = broadcasts.stream()
                            .map(BroadCast::getID) // 将 BroadCast 对象转换为 ID 值
                            .toArray(Integer[]::new);
                    BroadCastRequestVo broadCastRequestVo = new BroadCastRequestVo();
                    broadCastRequestVo.setBroadcastContent(monitor.getName() + "离线超时报警");
                    broadCastRequestVo.setIds(broadcastIds);
                    customConfigurationService.PlayBroadcastContent(broadCastRequestVo);
                }
            }
        }
        //查询掉线的监控点，并记录
        List<MonitorPoint> dropLineMonitors = monitorPointService.selectMonitorsThatDropLine();
        monitorPointService.recordDropLineMonitorList(dropLineMonitors);
    }
    /**
     * @author wxx
     * @description
     * @date 2024/10/23
     * 新增注释说明
     * 满足集团批量更新监控点
     *
     */
    @Transactional
    public void updateMonitorStatusTask2V2() {
        List<MonitorPoint> allList= new ArrayList<>();; // 存储所有监控点的列表
        List<MonitorPoint> list = new ArrayList<>(); // 存储过滤后的监控点列表
        System.out.println("开始执行-更新监控点：" + LocalTime.now()); // 打印当前时间

        Map<Long, SysDept> deptMap = genericMethodsService.getDeptMap();
        // 将 Map 转换为 List
        List<SysDept> deptList = deptMap.values().stream().collect(Collectors.toList());
        List<Long> unitCodes = new ArrayList<>();
        for (SysDept dept:deptList){
            unitCodes.add(dept.getUnitCode());
            System.out.println(dept.getUnitCode());
        }

        TUnitConfig tUnitConfig = new TUnitConfig();
        tUnitConfig.setUnitCodes(unitCodes);
        List<TUnitConfig> tUnitConfigs = tUnitConfigService.selectTUnitConfigList(tUnitConfig);

        // 根据 HK_SWITCH 的值决定从哪个服务获取监控点列表
        if ("true".equals(HK_SWITCH)) {
            allList = (List<MonitorPoint>) iSAPIService.getChannels().get("monitorPoints");
            TUnitConfig tUnitConfig1 = tUnitConfigs.get(0);
            Long unitCode = tUnitConfig1.getUnitCode();
            for (MonitorPoint moint :allList){
                moint.setModel("3");
                moint.setUnitCode(unitCode);
            }


        } else {
            //判断是否为集团模式 如果是则从各个一体极获取信息
            if(SYSTEM_PermissionVersion.equals("1")){

                //TODO
                for (TUnitConfig Unit: tUnitConfigs){

                    try {
                    List<MonitorPoint> monitorPoints = toMonitorListV2(jyService.getChannelListWithDeviceForUnitCodes(Unit),Unit.getUnitCode());
                    //判断是否需要过滤 _通道_
                    if (Unit.getJyChannelNameIsFilter()==1){
                        List<MonitorPoint> filteredList = new ArrayList<>();
                        for (MonitorPoint monitorPoint : monitorPoints) {
                            String name = monitorPoint.getName();
                            if (!name.contains("_通道_")) {
                                filteredList.add(monitorPoint); // 将不含 '_通道_' 的监控点添加到新的列表中
                            }
                        }
                        allList.addAll(filteredList);
                    }else {
                        allList.addAll(monitorPoints); // 将当前的 monitorPoints 添加到 allList
                    }
                    System.out.println(allList.size());
                    } catch (Exception e) {
                            // 记录异常信息
                            logger.error("Error processing unit code {}: {}", Unit.getUnitCode(), e.getMessage(), e);
                            // 继续处理下一个单元
                    }
                }

            }else {
                allList = toMonitorList(jyService.getChannelListWithDevice());

            }
        }


        // 如果是电子围栏系统，并且列表不为空，则更新监控点数据到监测设备
        if ("ef".equals(SYSTEM_NAME) && list != null && !list.isEmpty()) {
            // 这里可以添加具体的更新逻辑
        }

        // 将过滤后的监控点列表合并到数据库中的监控表
        System.out.println("将过滤后的监控点列表合并到数据库中的监控表"+allList.size());

        monitorPointService.mergeMonitorListToMonitorTable(allList);

        // 删除不在当前列表中的监控点
        monitorPointService.deleteMonitorNotInList(allList);

        // 获取需要发送离线告警的列表
        List<MonitorPoint> monitorListThatOfflineTimeout = monitorPointService.selectMonitorsOfflineTimeoutList();
        if (monitorListThatOfflineTimeout != null && !monitorListThatOfflineTimeout.isEmpty()) {
            // 插入这些监控点的离线超时报警记录
            monitorPointService.insertMonitorOfflineAlarmForUnitCodes(monitorListThatOfflineTimeout);

            // 更新这些监控点的离线超时报警发送状态为已发送
//            monitorPointService.updateAlarmStatusAsSentForUnitCodes(monitorListThatOfflineTimeout);

            //TODO 如果广播播放开关开启，则进行广播播报
//            if (servletContext.getAttribute("broadcastPlaySwitch").equals(1)) {
//                for (MonitorPoint monitor : monitorListThatOfflineTimeout) {
//                    // 获取与监控点关联的广播列表
//                    List<BroadCast> broadcasts = broadcastService.selectMonitorAssociatedBroadcasts(monitor.getApeId());
//
//                    // 提取广播 ID 数组
//                    Integer[] broadcastIds = broadcasts.stream()
//                            .map(BroadCast::getID)
//                            .toArray(Integer[]::new);
//
//                    // 创建广播请求对象
//                    BroadCastRequestVo broadCastRequestVo = new BroadCastRequestVo();
//                    broadCastRequestVo.setBroadcastContent(monitor.getName() + "离线超时报警");
//                    broadCastRequestVo.setIds(broadcastIds);
//
//                    // 播放广播内容
//                    customConfigurationService.PlayBroadcastContent(broadCastRequestVo);
//                }
//            }
        }

        // 将 List<MonitorPoint>  // 查询掉线的监控点，并记录
        List<MonitorPoint> isNotOnlineList = allList.stream()
                .filter(mp -> "2".equals(mp.getIsOnline())) // 过滤 isOnline 等于 "2" 的 MonitorPoint
                // 提取 isOnline 属性
                .collect(Collectors.toList());
//        List<MonitorPoint> dropLineMonitors = monitorPointService.selectMonitorsThatDropLineForUnitCodes();
        monitorPointService.recordDropLineMonitorListForUnitCodes(isNotOnlineList);
    }

//    /**
//     * 定时任务：添加一次监控点的当前状态信息，记录监控点的历史状态
//     */
//    @Scheduled(cron = "${scheduler.monitorStatusRecordCron}")
//    public void recordCurrentStatusOfAllMonitorTask() {
//        monitorPointHistoryService.recordCurrentStatusOfAllMonitoringPoint();
//    }

    /**
     * 定时任务：添加一次监控点的当前状态信息，记录监控点的历史状态
     *    变更原因：新增权限管理
     *     变更时间：2024-10-24
     */
    @Scheduled(cron = "${scheduler.monitorStatusRecordCron}")
    public void recordCurrentStatusOfAllMonitorTaskV2() {
        monitorPointHistoryService.recordCurrentStatusOfAllMonitoringPointForUnitCodes();
    }

    /**
     * 解析将从极云获取的监控点列表的json字符串
     */
    private List<MonitorPoint> toMonitorList (String monitorListJsonStr) {
        JSONArray monitorPointJsonArray = JSONObject.parseObject(monitorListJsonStr).getJSONObject("data").getJSONArray("data");
        int monitorCount = monitorPointJsonArray.size();
        ArrayList<MonitorPoint> res = new ArrayList<>(monitorCount);
        for (int i = 0;  i < monitorCount; i++) {
            JSONObject j = monitorPointJsonArray.getJSONObject(i);
            MonitorPoint monitorPoint = new MonitorPoint();
            monitorPoint.setIdx(j.getString("idx"))//通道序号
                        .setUnitCode(Long.parseLong(j.getString("unitCode")))//煤矿编码
                        .setApeId(j.getString("ape_id"))//通道国标id
                        .setResourceType(j.getString("resource_type"))//资源类型
                        .setSubType(j.getString("sub_type"))//通道子类型
                        .setName(j.getString("name"))//通道名称
                        .setModel(j.getString("model"))//通道类型
                        .setOwnerApsId(j.getString("dev_ape_id"))//所属设备id
                        .setOwnerApsName(j.getString("dev_name"))//所属设备name
                        .setOwnerApsIp(j.getString("ip_addr"))//所属设备ip
                        .setIsOnline(j.getString("is_online"))//在线状态
                        .setIsEnabled(j.getString("enabled"))//是否启用
                        .setOrgIndex(j.getString("org_index"))//组织id
                        .setOrgName(j.getString("org_name"))//组织名称
                        .setElevation(j.getDouble("altitude"))//海拔
                        .setMaxDivision(j.getInteger("max_division"))//最大分割数
                        .setCreateDate(j.getDate("create_time"))//创建时间
                        .setUpdateDate(j.getDate("update_time"));//更新时间
            res.add(monitorPoint);
        }
        return res;
    }

    /**
     * 解析将从极云获取的监控点列表的json字符串
     */
    private List<MonitorPoint> toMonitorListV2 (String monitorListJsonStr,Long unitCode) {
        JSONArray monitorPointJsonArray = JSONObject.parseObject(monitorListJsonStr).getJSONObject("data").getJSONArray("data");
        int monitorCount = monitorPointJsonArray.size();
        ArrayList<MonitorPoint> res = new ArrayList<>(monitorCount);
        for (int i = 0;  i < monitorCount; i++) {
            JSONObject j = monitorPointJsonArray.getJSONObject(i);
            MonitorPoint monitorPoint = new MonitorPoint();
            monitorPoint.setIdx(j.getString("idx"))//通道序号
                    .setUnitCode(unitCode)//煤矿编码
                    .setApeId(j.getString("ape_id"))//通道国标id
                    .setResourceType(j.getString("resource_type"))//资源类型
                    .setSubType(j.getString("sub_type"))//通道子类型
                    .setName(j.getString("name"))//通道名称
                    .setModel(j.getString("model"))//通道类型
                    .setOwnerApsId(j.getString("dev_ape_id"))//所属设备id
                    .setOwnerApsName(j.getString("dev_name"))//所属设备name
                    .setOwnerApsIp(j.getString("ip_addr"))//所属设备ip
                    .setIsOnline(j.getString("is_online"))//在线状态
                    .setIsEnabled(j.getString("enabled"))//是否启用
                    .setOrgIndex(j.getString("org_index"))//组织id
                    .setOrgName(j.getString("org_name"))//组织名称
                    .setElevation(j.getDouble("altitude"))//海拔
                    .setMaxDivision(j.getInteger("max_division"))//最大分割数
                    .setCreateDate(j.getDate("create_time"))//创建时间
                    .setUpdateDate(j.getDate("update_time"));//更新时间
            res.add(monitorPoint);
        }
        return res;
    }

}
